package com.nit.netty.handler;

import com.alibaba.fastjson.JSON;
import com.nit.netty.model.Request;
import com.nit.netty.model.Response;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.MethodUtils;

import java.util.Map;

/**
 * @Author: whb
 * @Description: 标注一个handler可以被多个channel共享
 * @CreateTime: 2020/8/21 13:40
 */
@ChannelHandler.Sharable
@Slf4j
public class NettyServerHandler extends AbstractNettyHandler{

    private final Map<String, Object> serviceMap;

    public NettyServerHandler(Map<String, Object> serviceMap) {
        this.serviceMap = serviceMap;
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        super.channelInactive(ctx);
        ctx.channel().close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Request request = JSON.parseObject(msg.toString(), Request.class);
        if ("heartBeat".equals(request.getMethodName())) {
            log.info("客户端心跳信息..."+ctx.channel().remoteAddress());
            return;
        }
        Response response = new Response();
        response.setRequestId(request.getId());
        try {
            Object res = this.handler(request);
            response.setData(res);
        } catch (Exception e) {
            response.setCode(-1);
            response.setError(e.getMessage());
            log.error("请求调用失败", e);
        }
        ctx.writeAndFlush(response);
    }

    private Object handler(Request request) throws Exception {
        String className = request.getClassName();
        // 根据className去拿反射的实现类
        Object serviceBean = serviceMap.get(className);
        String methodName = request.getMethodName();
        Object[] parameters = request.getParameters();
        return MethodUtils.invokeMethod(serviceBean, methodName, parameters);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("网络异常.", cause);
        ctx.close();
    }

}
